﻿using System;
using System.Data;
using System.Configuration;

using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;

using System.IO;
using System.ComponentModel;
using System.Collections;
using System.Text.RegularExpressions;
using System.Text;
using TA.DotNetUtils;

namespace TA.Turbo.Controls
{
	/// <summary>
	/// Base class for all controls that display and allow selecting from a list of items.
	/// </summary>
	[ParseChildren(true), PersistChildren(false)]
	public abstract class BaseListControl : BaseFieldControl<string>, IListControl
	{
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		public BaseListControl()
		{
			this.Tag = HtmlTextWriterTag.Select;

			ListItemCollection lic = new ListItemCollection();
			lic._owner = this;
			ViewState["Items"] = lic;
		}
		#endregion
		#region METHODS
		/// <summary>
		/// Creates the list items by enumerating the specified data source and using the specified value, text and category fields to set properties of the created list items.
		/// </summary>
		/// <param name="dataSource"></param>
		/// <param name="valueField"></param>
		/// <param name="textField"></param>
		/// <param name="categoryField"></param>
		public void DataBind(object dataSource, string valueField, string textField, string categoryField)
		{
			ListControlCommon.DataBind(this, dataSource, valueField, textField, categoryField);

		}
		/// <summary>
		/// Adds the first items to the collection which always precede the data bound items.
		/// </summary>
		public virtual void AddFirstItems()
		{
			ListControlCommon.AddFirstItems(this);
		}
		#endregion
		#region PROPS
		#region DEF
		/// <summary>
		/// Props.
		/// </summary>
		protected static new Properties _clientProperties = Define(BaseFieldControl<string>._clientProperties, ListControlCommon.Properties);
		/// <summary>
		/// Props.
		/// </summary>
		public override Properties ClientProperties
		{
			get
			{
				return _clientProperties;
			}
		}
		#endregion
		/// <summary>
		/// List of top-level items in this list control (options and/or groups).
		/// </summary>
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Category("Behavior")]
		public ListItemCollection Items
		{
			get
			{
				return GetProperty<ListItemCollection>("Items");
			}
		}
		/// <summary>
		/// Gets all options in this list control (no groups).
		/// </summary>
		[Browsable(false)]
		public ListItem[] Options
		{
			get
			{
				return ListControlCommon.GetOptions(this);
			}
		}
		/// <summary>
		/// The CSS class applied to all items which don't have a class individually specified for them.
		/// </summary>
		[DefaultValue("")]
		[Category("Appearance")]
		public string ItemCssClass
		{
			get
			{
				return this.GetProperty<string>("ItemCssClass");
			}
			set
			{
				this.ViewState["ItemCssClass"] = value;
			}
		}
		/// <summary>
		/// The CSS class applied to all groups which don't have a class individually specified for them.
		/// </summary>
		[DefaultValue("")]
		[Category("Appearance")]
		public string GroupCssClass
		{
			get
			{
				return this.GetProperty<string>("GroupCssClass");
			}
			set
			{
				this.ViewState["GroupCssClass"] = value;
			}
		}
		/// <summary>
		/// The items which are automatically inserted at the top of list when performing DataBind. If this is empty, no items will be inserted. Used for stuff like "Select a country" etc.
		/// </summary>
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Category("Behavior")]
		public List<ListItem> FirstItems
		{
			get
			{
				return this._firstItems;
			}
		}
		/// <summary>
		/// The items which are automatically inserted at the top of each category when performing DataBind. If this is empty, no items will be inserted. Used for stuff like "All in US" under the category "US", etc.
		/// </summary>
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Category("Behavior")]
		public List<ListItem> CategoryFirstItems
		{
			get
			{
				return this._categoryFirstItems;
			}
		}
		#endregion
		#endregion
		#region INTERNAL
		#region VARS
		List<ListItem> _categoryFirstItems = new List<ListItem>(),
			_firstItems = new List<ListItem>();
		#endregion
		#region Methods
		#region INIT
		/// <summary>
		/// Init.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);

		}
		/// <summary>
		/// Registers SelectControl.js.
		/// </summary>
		protected internal override void RegisterIncludes(IncludeCollection includes)
		{
			base.RegisterIncludes(includes);

			ListControlCommon.RegisterIncludes(this, includes);

			// the following includes for field list controls (which are rendered as SELECT controls)
			includes.Add(Script.StringBuilder);
			includes.Add(Script.RegExp_Matches);
			includes.Add(Script.Array_IndexWhere);
			includes.Add(new ScriptResourceInclude("TA.Turbo.Res.JS.Simple.SelectControl.js", typeof(BaseCommandControl)));
		}
		#endregion
		#region RENDER
		/// <summary>
		/// Renders the list items contained within this control.
		/// </summary>
		/// <param name="writer"></param>
		protected override void RenderContents(HtmlTextWriter writer)
		{
			ListControlCommon.RenderContents(this, writer);
		}
		/// <summary>
		/// Renders a list item group by outputting "OPTGROUP" tag.
		/// </summary>
		/// <param name="writer"></param>
		/// <param name="group"></param>
		public void RenderItemGroup(HtmlTextWriter writer, ListItem group)
		{
			writer.AddAttribute("label", group.Text);
			writer.RenderBeginTag("optgroup");

			ListControlCommon.RenderItemGroupChildren(this, writer, group);

			writer.RenderEndTag();
		}
		/// <summary>
		/// Renders a list item by outputting an OPTION tag.
		/// </summary>
		/// <param name="writer"></param>
		/// <param name="item"></param>
		public virtual void RenderItemOption(HtmlTextWriter writer, ListItem item)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Value, item.Value);
			if (string.Equals(this.Value, item.Value))
				writer.AddAttribute(HtmlTextWriterAttribute.Selected, "selected");
			writer.RenderBeginTag(HtmlTextWriterTag.Option);
			writer.Write(((ListItem)item).Text);
			writer.RenderEndTag();
		}
		#endregion
		#region DATABIND
		#endregion
		#endregion
		#endregion
	}
}